#
# Super Goonie lagzplot 2D!
#
# A game by Duckmonster Prime.
#
# GPL 3.0 & GPL 1 (Gnu Public Licence v 3.0 & Goon Pubbie Licence v1)
# This means "If you copy this shit, include the code. If you change the code, you must still include the code.
# The Goon Pubbie Licence means : All your base are belong to us. This is translated from english to pubbie catchphrase.
#
# Flags
do_profile = 0  # Set to 1 to invoke code profiler
#

import pygame , math , sys
import decimal
from levels import level
from pygame.locals import *
clock = pygame.time.Clock()
from pygame import mixer
pygame.init()
mixer.init()

font = pygame.font.Font('freesansbold.ttf',15)



#Boops and bops
sound = {}
sound ['gunshot1'] = pygame.mixer.Sound('audio/02.wav') #Light gunshot
sound ['gunshot2'] = pygame.mixer.Sound('audio/24.wav') #Pew pew!
sound ['explode1'] = pygame.mixer.Sound('audio/explotion.wav') #BOOM!
sound ['explode2'] = pygame.mixer.Sound('audio/explosion_03L.wav') #Smaller boom

#
#
# Consts etc
screen=pygame.display.set_mode((1024,768),FULLSCREEN|HWSURFACE|DOUBLEBUF)
pygame.mouse.set_visible(0)
background = pygame.transform.scale(pygame.image.load('gfx/hubble2.jpg'),(1024,768)).convert()

D = decimal.Decimal

#
# Utils etc 
#



def dist(startp,endp):
        x1,y1 = startp
        x2,y2 = endp
        return math.sqrt(((x1-x2)**2) + ((y1-y2)**2))


def paint_background(): #REPLACE LATER ON!
	global screen
	global background
	screen.blit(background,(0,0))
        
def show():
	pygame.display.flip()
        
def paint_targetbox(pos,image,healthcur,healthmax,name):
        x = (pos *150) - 130
        #Draw the box.
        global screen
        pygame.draw.rect (screen,(255,255,255),Rect(x,20,100,100),1)
        screen.blit(pygame.transform.scale(image,(100,100)),(x,20))
        paint_bargraph ((x,130,100,10),healthcur,healthmax)
        simpletext ('Enemy  : '+name,15,(x,145))
        simpletext ('Shields: %'+str(((healthmax/healthcur)*100)),15,(x,155))
        
def paint_bargraph(rect,maxval,val):
        x,y,w,h = rect
        ratio = val/maxval
        pygame.draw.rect (screen,(0,255,0),Rect(x,y,(w * ratio),h),0)
        pygame.draw.rect (screen,(255,255,255),Rect(x,y,w,h),1)
        

def simpletext (message,size,pos):
 #       font = pygame.font.Font (None,size)
        
        global font
        text = font.render(message,1,(255,255,255))
        x,y = pos
        textRect = text.get_rect()
        textRect.centerx = x
        textRect.centery = y
        textRect.x = x; textRect.y = y
        screen.blit(text, textRect)

def draw_sidebar(myship,sprgroup):
        pygame.draw.rect (screen, (255,255,255),Rect (800,20,200,500),1)
        pygame.draw.rect (screen, (255,255,255),Rect (800,20,200,20),1)
        pygame.draw.rect (screen, (255,255,255),Rect (800,20,20,500),1)
        pygame.draw.rect (screen, (255,255,255),Rect (800,20,70,500),1)
        simpletext ('Icn',15,(804,26))
        simpletext ('Distance',15,(824,26))
        simpletext ('Object',15,(874,26))
        ctr = 0
        for item in sprgroup:
                ctr += 1
                distance = dist(myship.position,item.position)
                simpletext (item.name,15,(874,26 + (ctr*20)))
                simpletext (str(D(str(distance/10)).quantize(D('0.01')))+'km',15,(824,26 + (ctr*20)))
                pygame.draw.line (screen,(255,255,255),(800,40 + (ctr * 20)),(1000,40+(ctr * 20)),1)
                if item.AQUIRED == 1:
                        pygame.draw.rect (screen, (255,0,0),Rect(804,24 + (ctr*20),12,12),3)
                elif item.LOCKED > 0:
                        pygame.draw.rect (screen, (255,255,0),Rect(804,24 + (ctr*20),12,12),3)
                else:
                        pygame.draw.rect (screen, (255,255,255),Rect(804,24 + (ctr*20),12,12),3)

def draw_hud (myship):
        paint_bargraph ((20,700,200,20),myship.HITPOINTS,myship.HEALTH)
        simpletext ('Shields: %'+str(((myship.HEALTH/myship.HITPOINTS)*100)),20,(20,722))
                
class sprite (pygame.sprite.Sprite):
		TARGMODE = 0
		TARGRAD = 300
		TARGCOL = (255,50,50)
		LOCKED = 0
		AQUIRED = 0
		def __init__(self,image,position,z):
			pygame.sprite.Sprite.__init__(self)
			self.src_image = pygame.image.load('gfx/'+image).convert()
			self.position = position
			self.speed = self.direction = 0
			self.k_left = self.k_right = self.k_down = self.k_up = 0 

			
		def update (self,deltat):
                        global lockcount
                        global locks
                        if self.AQUIRED == 1:
                                locks += 1
                                if locks > lockcount:
                                        lockcount = locks

                                paint_targetbox(locks,self.src_image,self.HITPOINTS,self.HEALTH,self.name) #Insert health box later!
                                
                        # For standard turn + speed
                        #
                        #
			self.speed += (self.k_up  + self.k_down)
			if self.speed > self.MAX_FORWARD_SPEED:
				self.speed = self.MAX_FORWARD_SPEED
			if self.speed < -self.MAX_REVERSE_SPEED:
				self.speed = -self.MAX_REVERSE_SPEED
			self.direction += (self.k_right + self.k_left)
			x,y =  self.position
			#self.speed = -1
			#self.direction = 45
			#self.direction = 0
			rad = self.direction *math.pi / 180
			x+= -self.speed*math.sin (rad)
			y+= -self.speed*math.cos (rad)
			#
			#
			#
			if x < 1 : x = 1023
			elif x > 1023 : x = 1
			if y < 1 : y = 766
			elif y > 766 : y = 1
			self.position = (x,y)
			#print self.k_left , self.k_right, self.k_up , self.k_down
			self.image = pygame.transform.rotate (self.src_image,self.direction)
			self.rect = self.image.get_rect()
			self.rect.center = self.position
			global screen
			if self.TARGMODE == 1:
				pygame.draw.circle(screen,(255,128,128),self.position,self.TARGRAD,1)
			elif self.TARGMODE == 2:
				pygame.draw.circle(screen,(255,255,255),self.position,self.TARGRAD,1)
				pygame.draw.circle(screen,(200,200,200),self.position,self.TARGRAD * 0.75,1)
				pygame.draw.circle(screen,(128,128,128),self.position,self.TARGRAD * 2,1)
				pygame.draw.circle(screen,(75,75,75),self.position,self.TARGRAD * 4,1)
			if (self.LOCKED == 1):
                                lockcount = 0 #RESET. It'll be right by recount.
			if ((self.LOCKED >0) and (self.LOCKED < 40)):
                                if (self.LOCKED % 4) == 1:
        				pygame.draw.rect (screen,(255,255,0),Rect(x-50,y-50,100,100),1)
        				
				self.LOCKED += 1
			elif (self.LOCKED == 40):
                                pygame.draw.rect (screen,(255,0,0),Rect(x-50,y-50,100,100),1)
                                self.AQUIRED =1
                        if ((self.LOCKED == 25) and (lockcount > 2)):
                                self.LOCKED = 0
                                self.AQUIRED = 0
                                


#
# Definitions
#

class gune_myship (sprite):

	def __init__(self,position):
		self.MAX_FORWARD_SPEED = 25
		self.MAX_REVERSE_SPEED = 25
		self.ACCELERATION = 2
		self.TURN_SPEED = 5
		self.TARGRAD = 150
		self.TARGMODE = 2
		self.HITPOINTS = 3000
		self.HEALTH = 3000
		sprite.__init__(self,'rifter.gif',position,1)

class weapon (sprite):
        
        def __init__(self,image,gun,target):
                #
                self.image = image
                self.gun = gun
                self.target = target
                self.position = gun.position
                self.path = 0
                self.processed = 0
                self.gunspeed = 10.0
                sound[self.sound].play()
                sprite.__init__(self,image,self.position,1)
                self.killme = 0
        
        def update(self,deltat):
                self.path += 1
                if self.path > self.gunspeed:
                        self.path = self.gunspeed #Now transmute!
                        if self.processed == 0:
                                self.processed = 1
                                self.target.HEALTH = self.target.HEALTH - self.damage # self.target.HEALTH - self.damage
                                self.killme = 1
                                sound['explode2'].play()                        
                                #
                        
                #Calculate position
                g_x,g_y = self.gun.position
                t_x,t_y = self.target.position
                
                d_x = (t_x - g_x) / self.gunspeed
                d_y = (t_y - g_y) / self.gunspeed
                b_x = g_x + (d_x * self.path)
                b_y = g_y + (d_y * self.path)
                self.position = (b_x,b_y)
		self.image = self.src_image
		self.rect = self.image.get_rect()
		self.rect.center = self.position
                if self.target.HEALTH < 1.0:
                        self.target.AQUIRED = 0
                        self.target.LOCKED = 0
                      
                        
       

class mousepointer(sprite):
	def __init__(self,position):
		self.MAX_FORWARD_SPEED = 10
		self.MAX_REVERSE_SPEED = 10
		self.ACCELERATION = 2
		self.TURN_SPEED = 5
		sprite.__init__(self,'targ.gif',position,1)

	def update(self,deltat):
			self.image = self.src_image
			self.rect = self.image.get_rect()
			self.rect.center = pygame.mouse.get_pos()

class bad_enemy(sprite):
	def __init__(self,graphic,position):
		self.MAX_FORWARD_SPEED = 10
		self.MAX_REVERSE_SPEED = 10
		self.ACCELERATION = 2
		self.TURN_SPEED = 5
		self.TARGMODE = 1
		self.HEALTH = self.HITPOINTS 
		sprite.__init__(self,graphic,position,1)

#	def update(self,deltat):
#			self.image = self.src_image
#			self.rect = self.image.get_rect()
#			self.rect.center = self.position

#Test code!

class bullet (weapon):
        def __init__(self,gun,target):   #Starting bullet
                self.gunspeed = 10.0
                self.damage = 50.0
                self.sound = 'gunshot1'
                weapon.__init__(self,'bullet.gif',gun,target)


class bullet2 (weapon):
        def __init__(self,gun,target): #Low level enemy bullet
                self.gunspeed = 10.0
                self.damage = 40.0
                self.sound = 'gunshot2'
                weapon.__init__(self,'bullet.gif',gun,target)
	
class bad_caracal (bad_enemy):
	def __init__(self,position):
		self.TARGRAD = 100
		self.HITPOINTS = 500
		self.name = "Caracal"
		self.bullet = "bullet2"
		bad_enemy.__init__(self,'caracal.gif',position,)

class bad_geddon (bad_enemy):
	def __init__(self,position):
		self.TARGRAD = 140
		self.HITPOINTS = 1000
		self.name = "Armagedon"
		self.bullet = "bullet2"
		bad_enemy.__init__(self,'geddon.gif',position,)
class bad_badger (bad_enemy):
	def __init__(self,position):
		self.TARGRAD = 110
		self.LOCKED = 0
		self.HITPOINTS = 500
		self.name = "Badger I"
		self.bullet = "bullet2"
		bad_enemy.__init__(self,'badger.gif',position,)
class bad_osprey (bad_enemy):
	def __init__(self,position):
		self.TARGRAD = 75
		self.LOCKED = 0
		self.HITPOINTS = 250
		self.name = "Osprey"
		self.bullet = "bullet2"
		bad_enemy.__init__(self,'osprey.gif',position,)


enemyarray = {  'caracal': bad_caracal,
		'osprey' : bad_osprey,
		'badger' : bad_badger,
		'geddon' : bad_geddon}

weaponarray = { 'bullet': bullet,
                'bullet2': bullet2,

                }

def mainloop(level):
        #Get the sounds in!
        mixer.music.load('music/godzilla.ogg')
        mixer.music.play(-1)
        wave = 0
        cycle = 0
        cycle2 = 0
	lockcount = 0
	gun_fired = 0
	enemy_gun_fired = 0
	rect = screen.get_rect()
	myship = gune_myship(rect.center)

	mouse = mousepointer(rect.center)
	myship_group = pygame.sprite.RenderPlain(myship)
	mouse_group = pygame.sprite.RenderPlain(mouse)
	

	global enemyarray
	enemys = []


	enemy_group= pygame.sprite.RenderPlain(enemys)
        bullet_group = pygame.sprite.RenderPlain([])
	paint_background()
	show()
	paint_background()
	show()

        levelover = 0

            
	while (levelover == 0):
                if (enemy_group.sprites() == []):
                                enemys = []
                                wave += 1
                                if level['waves'].has_key(wave):
                                	leveldata = level['waves'][wave]['data']
                                        for item in leveldata:                                         
                                                enemyitem = enemyarray[item['type']](rect.center)
                                                enemyitem.k_down = 1
                                                enemyitem.MAX_FORWARD_SPEED = item['speed']
                                                enemyitem.k_right = item['turn']
                                                enemyitem.position = item['position']
                                                enemys.append(enemyitem)
                                 	enemy_group= pygame.sprite.RenderPlain(enemys)
                                else:
                                        # LEVEL OVER!
                                        levelover = 1
		deltat =clock.tick(10)
		paint_background()


		
		myship_group.update(deltat)
		myship_group.draw(screen)
		enemy_group.update(deltat)
		enemy_group.draw(screen)
                bullet_group.update(deltat)
                for item in bullet_group:
                        if item.killme == 1:
                                bullet_group.remove(item)
                bullet_group.draw(screen)
                mouse_group.update(deltat)
                mouse_group.draw(screen)
                draw_sidebar(myship,enemy_group)
                draw_hud(myship)
                show()
                myship_group.clear(screen,background)
                mouse_group.clear(screen,background)
                enemy_group.clear(screen,background)		

                               

		for event in pygame.event.get():
			if not hasattr(event,'key'): continue
			down = event.type == KEYDOWN
			if event.key == K_d: myship.k_right = down * -5
			elif event.key == K_a: myship.k_left = down * 5
			elif event.key == K_w: myship.k_up = down * 2
			elif event.key == K_s: myship.k_down = down * -2
			elif event.key == K_SPACE:  #NEEDS TO BE MOUSE :psyduck: <-- figure it out later
				clickygroup = pygame.sprite.spritecollide(mouse,enemy_group,False)
				for i in clickygroup:
					i.LOCKED=1

				

			elif event.key == K_ESCAPE: 
				return

		#Tick over cycle counter
		cycle += 1
		if cycle > 5:
                        cycle = 1
                        if gun_fired == 1:
                                gun_fired = 0 # Fire another round!
		cycle2 += 1
		if cycle2 > 7:
                        cycle2 = 1
                        if enemy_gun_fired == 1:
                                enemy_gun_fired = 0 # Fire another round!                        

		
                global lockcount
                global locks
                locks = 0
				

                ####
                # Calculate Fire.
                #
                # Replace next section with smarter code.
                loadedgun = 'bullet'
                #
                #
                for item in enemy_group:
                        distance = dist(myship.position,item.position)
                        #I'm shooting!
                        if ((distance < myship.TARGRAD) and (gun_fired == 0) and (item.AQUIRED == 1)): #(If in range!)
                                gun_fired = 1 #lock
                                newbullet = weaponarray['bullet'](myship,item)
                                bullet_group.add(newbullet)
                        if item.HEALTH < 1.0:
                                enemy_group.remove(item) #Die bitch
                                sound['explode1'].play()
                        #They are shooting!
                        if ((distance < item.TARGRAD) and (enemy_gun_fired == 0)): # and (cycle2 == 1)): #(If in range!)
                                enemy_gun_fired = 1 #lock
                                newbullet = weaponarray[item.bullet](item,myship)
                                bullet_group.add(newbullet)
                        if myship.HEALTH < 1.0:
                                 sys.exit(0) # :(

                        
                                

	
def main():
        mainscreen = pygame.transform.scale(pygame.image.load('gfx/titlescreen.jpg'),(1024,768))
        mixer.music.load('music/POPTUNE.XM')
        mixer.music.play(-1)
        while 1: 
                screen.blit(mainscreen,(0,0))
                show() 
                finished = 0
                while finished == 0:
                        for event in pygame.event.get():
                                if not hasattr(event,'key'): continue
                                down = event.type == KEYDOWN
                                if event.key == K_SPACE: finished = 1
                                elif event.key == K_ESCAPE:
                                        sys.exit(0)
                mainloop(level[1])

if do_profile == 1:
        import hotshot,hotshot.stats
        prof = hotshot.Profile('c:\prof.dat')
        result = prof.runcall(main)
        prof.close()
        print "PROFILE DONE, result=",result,type(result)
        stats = hotshot.stats.load("c:\prof.dat")
        stats.strip_dirs()
        stats.sort_stats('time', 'calls')
        stats.print_stats(200)
else:
        main()

